import os
import Logger
from Function import People, Database, Data, FileOperation

import re
import time
import tkinter as tk
import tkinter.ttk
import traceback
from tkinter import messagebox
import random
import pyTFC

database_address = "Database/Data.db"


def add_task_confirm(task_content, deadline, note, add_task_window):
    # 时间数据处理
    deadline = f"2024-{deadline}:00:00"
    try:
        Database.add_data(database_address,
                               "task",
                               ["taskDetails", "deadline", "notes"],
                               [task_content, deadline, note]
                               )
    except:
        logger.error(traceback.format_exc())
        messagebox.showerror('失败', "任务添加失败，查看日志文件获取详情")
    else:
        tk.Label(add_task_window, text="添加成功", fg="red").grid(row=5, column=1)


def add_task():
    # 创建子窗口
    add_task_window = tk.Tk()
    add_task_window.geometry("500x300")
    add_task_window.title('添加任务')  # 设置窗体的名称

    # 标签
    tk.Label(add_task_window, text='任务内容:').grid(row=1, column=1)
    tk.Label(add_task_window, text='截止时间').grid(row=2, column=1)
    tk.Label(add_task_window, text='备注').grid(row=3, column=1)
    # 任务内容输入框
    task_content = tk.Entry(add_task_window)
    task_content.grid(row=1, column=2)
    # 截止时间输入框
    deadline = tk.Entry(add_task_window)
    deadline.grid(row=2, column=2)
    # 备注输入框
    note = tk.Entry(add_task_window)
    note.grid(row=3, column=2)

    # 添加按钮
    tk.Button(add_task_window,
              text='添加',
              command=lambda: add_task_confirm(task_content.get(),
                                               deadline.get(),
                                               note.get(),
                                               add_task_window)
              ).grid(row=4, column=1)
    tk.Button(add_task_window, text='退出', command=add_task_window.destroy).grid(row=4, column=2)
    # 窗口循环
    add_task_window.mainloop()


def files_display(file_frame, window_width):
    # 定义常量
    head_font_size = 12
    content_font_size = 14
    this_num = 0
    color_list = ["blue", "green", "purple", "orange"]

    # 读取数据库，获取文件夹路径列表
    folder_list = Database.read_data_to_list(database_address, "folder_list")
    # 获取班级学生的信息列表(姓名，学号）
    students_info_list = Database.read_data_to_list(database_address, "students")
    # 获取班级学生的学号
    student_id_number_list = Database.read_column_data_to_list(database_address, "students", "ID")
    # 获取班级学生的姓名
    student_name_list = Database.read_column_data_to_list(database_address, "students", "name")

    # 判断文件夹列表是否为空
    if len(folder_list) == 0:
        # 文件夹列表为空，就直接结束
        tk.Label(file_frame, text='列表为空，输出完毕').pack()
    else:
        # 遍历文件夹列表
        for folder in folder_list:
            # 生成随机数，如果随机数和上一轮重复，则另外生成
            last_num = this_num
            while last_num == this_num:
                this_num = random.randint(0, len(color_list) - 1)

            # 获取文件夹中所有文件的名称
            try:
                file_name = FileOperation.get_file_full_name_from_folder(folder[1])
            except FileNotFoundError:
                tk.Label(file_frame, text=f'未发现文件夹：{folder[1]}', font=("微软雅黑", head_font_size)).pack()
                tk.Label(file_frame, text='建议删除此文件夹路径', font=("微软雅黑", head_font_size)).pack()
                break
            # 文件名称根据正则表达式匹配
            num_id_list = []
            for item in file_name:
                # 匹配规则：20xx21xxxx
                result = re.search(r'20\d{2}21\d{4}', item)
                try:
                    # 匹配到内容
                    num_id_list.append(result.group())
                except AttributeError:
                    # 没有匹配到内容，不处理
                    pass

            # 判断id列表是否为空
            if len(num_id_list) == 0:
                # id列表为空，说明文件名称没有学号，就以姓名统计

                # 提交的学生名字列表
                commit_students_name_list = []
                # 未提交的学生名字列表，默认所有学生均未提交
                uncommit_students_name_list = student_name_list

                for item in file_name:
                    # 使用正则表达式来匹配中文名字，假设名字由2到3个汉字组成
                    result = re.search(r'\b[\u4e00-\u9fa5]{2,3}\b', item)
                    try:
                        commit_students_name_list.append(result.group())
                    except AttributeError:
                        # 没有匹配到内容，不处理
                        pass

                # 显示统计的文件夹信息
                tk.Label(file_frame,
                         text=f"文件夹ID：{folder[0]}",
                         fg=color_list[this_num],
                         font=("微软雅黑", head_font_size)).pack(anchor="w")
                tk.Label(file_frame,
                         text=f"文件夹路径：{folder[1]}",
                         fg=color_list[this_num],
                         font=("微软雅黑", head_font_size)).pack(anchor="w")
                # 输出结果
                tk.Label(file_frame,
                         text=f"已经提交（{len(commit_students_name_list)}）人：",
                         fg=color_list[this_num],
                         font=("微软雅黑", head_font_size)).pack(anchor="w")
                tk.Label(file_frame,
                         text=" ".join(commit_students_name_list),
                         fg=color_list[this_num],
                         justify="left",
                         wraplength=window_width,
                         font=("微软雅黑", head_font_size),
                         anchor="w").pack(anchor="w")
                # 在未提交学生姓名列表中去除已经提交的学生，剩下的就是未提交的学生
                for name in commit_students_name_list:
                    if name in uncommit_students_name_list:
                        uncommit_students_name_list.remove(name)
                # 未提交学生
                tk.Label(file_frame,
                         text=f"未提交（{len(uncommit_students_name_list)}）人：",
                         fg=color_list[this_num],
                         font=("微软雅黑", head_font_size)).pack(anchor="w")
                tk.Label(file_frame,
                         text=" ".join(uncommit_students_name_list),
                         fg=color_list[this_num],
                         justify="left",
                         wraplength=window_width,
                         font=("微软雅黑", head_font_size),
                         anchor="w").pack(anchor="w")

            else:
                # id列表不为空，说明文件名称以学号统计
                # 计数
                count_result_dict = Data.list_count(student_id_number_list, num_id_list)

                # 获取计数结果
                all_students_dic = People.getAllStudentsDic(count_result_dict, student_id_number_list)
                undo_id_list = all_students_dic.get('undo')
                done_id_list = all_students_dic.get('done')

                # 将id转换为对应的name
                undo_name_list = []
                done_name_list = []
                for item in undo_id_list:
                    for info in students_info_list:
                        if item in info:
                            undo_name_list.append(info[0])
                for item in done_id_list:
                    for info in students_info_list:
                        if item in info:
                            done_name_list.append(info[0])

                # 显示统计的文件夹
                print(f"文件夹ID：{folder[0]}\n文件夹路径：{folder[1]}\n")
                # 输出ID
                print(f"未完成（{len(undo_id_list)}人）：{' '.join(undo_id_list)}")
                print(f"已完成（{len(done_id_list)}人）：{' '.join(done_id_list)}")
                print("")
                # 输出姓名
                print(f"未完成（{len(undo_name_list)}人）：{' '.join(undo_name_list)}")
                print(f"已完成（{len(done_name_list)}人）：{' '.join(done_name_list)}")
                print("\n\n")


def task_display(task_frame):
    # 获取数据
    no_time_task_list = []
    time_task_list = []
    task_list = Database.read_data_to_list(database_address, "task")
    for task in task_list:
        try:
            time.strptime(task[2], "%Y-%m-%d %H:%M:%S")
            time_task_list.append(task)
        except ValueError:
            no_time_task_list.append(task)

    # 有时间的任务列表以时间排序
    time_task_list.sort(key=lambda task_item: time.mktime(time.strptime(task_item[2], "%Y-%m-%d %H:%M:%S")),
                        reverse=False)

    # 变量定义
    color_list = ["blue", "green", "purple"]
    id_label_list = []
    task_label_list = []
    time_label_list = []
    content_font_size = 14
    content_font = "HarmonyOS Sans SC"
    font = (content_font, content_font_size)
    wrap_length = 330
    this_num = 0
    # 设置表头名称
    tk.Label(task_frame, text="任务汇总", font=font).grid(row=0, column=1, columnspan=3)
    tk.Label(task_frame, text="ID", font=font).grid(row=1, column=1)
    tk.Label(task_frame, text="内容", font=font).grid(row=1, column=2)
    tk.Label(task_frame, text="截止时间", font=font).grid(row=1, column=3)

    # 生成标签内容
    for item in time_task_list + no_time_task_list:
        # 生成随机数，如果随机数和上一轮重复，则另外生成
        last_num = this_num
        while last_num == this_num:
            this_num = random.randint(0, len(color_list) - 1)

        # 尝试处理时间变量
        try:
            deadline_stamp = time.mktime(time.strptime(item[2], "%Y-%m-%d %H:%M:%S"))
            now_time_stamp = time.time()

            remaining_all_second = deadline_stamp - now_time_stamp
            remaining_all_hour = remaining_all_second / 3600

            remain_day = (remaining_all_hour - remaining_all_hour % 24) / 24
            remain_hour = remaining_all_hour % 24
        except ValueError:
            # 任务没有时间参数
            id_label_list.append(tk.Label(task_frame,
                                          anchor="w",
                                          font=font,
                                          fg=color_list[this_num],
                                          text=item[0]))
            task_label_list.append(tk.Label(task_frame,
                                            anchor="w",
                                            justify="left",
                                            fg=color_list[this_num],
                                            font=font,
                                            wraplength=wrap_length,
                                            text=item[1]
                                            ))
            time_label_list.append(tk.Label(task_frame,
                                            anchor="w",
                                            font=font,
                                            text=item[3]
                                            ))
        else:
            # 任务有时间参数
            if deadline_stamp > now_time_stamp:
                # 如果任务未过期，则显示
                id_label_list.append(tk.Label(task_frame,
                                              anchor="w",
                                              font=font,
                                              fg=color_list[this_num],
                                              text=item[0]))
                task_label_list.append(tk.Label(task_frame,
                                                anchor="w",
                                                justify="left",
                                                fg=color_list[this_num],
                                                font=font,
                                                wraplength=wrap_length,
                                                text=item[1]))
                if deadline_stamp - now_time_stamp < 86400:
                    # 剩余时间小于一天
                    time_label_list.append(tk.Label(task_frame,
                                                    anchor="w",
                                                    fg="red",
                                                    font=font,
                                                    text=f"不足一天\n{item[2][5:16]}\n({int(remain_hour)}小时)"
                                                    ))
                else:
                    # 剩余时间不小于一天
                    time_label_list.append(tk.Label(task_frame,
                                                    anchor="w",
                                                    font=font,
                                                    text=f"{item[2][5:16]}\n({int(remain_day)}天{int(remain_hour)}小时)"
                                                    ))
            if now_time_stamp - deadline_stamp > 604800:
                # 任务已经过期7天，则删除
                Database.delete_data_by_ID(database_address, "task", item[0])

    # 放置标签
    for index in range(len(id_label_list)):
        id_label_list[index].grid(row=index + 2, column=1, sticky="n")
        task_label_list[index].grid(row=index + 2, column=2, sticky="nw")
        time_label_list[index].grid(row=index + 2, column=3, sticky="n")


def main():
    # 初始化主窗口
    root = tk.Tk()
    root.title('Class Affairs')  # 设置窗体的名称
    root.state('zoomed')  # 窗口最大化
    # 刷新root窗口，否则获取的winfo_width()值为1
    root.update()
    # 获取窗口宽度
    window_width = root.winfo_width()

    # 菜单栏
    top = tk.Menu(root)
    top.add_command(label='添加任务', command=add_task)
    top.add_command(label='课表查询')
    top.add_command(label='文件收集')
    top.add_command(label='刷新')
    top.add_command(label='退出', command=root.destroy)
    root.config(menu=top)

    # Canvas,Scrollbar放置在主窗口上
    canvas = tk.Canvas(master=root)
    scro = tk.Scrollbar(master=root)
    scro.pack(side='right', fill='y')
    canvas.pack(anchor="nw")

    # 在画布上创建多选项卡
    notebook = tkinter.ttk.Notebook(canvas)
    task_frame = tk.Frame()
    file_frame = tk.Frame()
    notebook.add(task_frame, text='任务管理')
    notebook.add(file_frame, text='文件收集')
    notebook.pack(fill=tkinter.BOTH, expand=True)

    # 将多选项卡添加至画布上
    canvas.create_window((0, 0), window=notebook, anchor="nw")

    # 任务显示
    task_display(task_frame)
    # 文件收集显示
    files_display(file_frame, window_width)

    # 更新多选项卡，不然没有滚动效果
    notebook.update()
    # 将滚动按钮绑定在画布上
    canvas.bind_all("<MouseWheel>", lambda event: canvas.yview_scroll(-1 * (int(event.delta / 120)), "units"))
    canvas.configure(yscrollcommand=scro.set, scrollregion=canvas.bbox("all"))
    scro.config(command=canvas.yview)

    root.mainloop()


if __name__ == "__main__":
    # 配置logger
    logger = Logger.logger_config("ClassAffairsGUI.log", "ClassAffairsGUI")
    # 对全局的报错进行捕获，并打印报错信息
    try:
        main()
    except:
        os.system('cls')
        logger.error(traceback.format_exc())
        messagebox.showerror('错误', "发生了异常，请查看日志文件")
